package dao

import (
	"context"
	"fmt"
	"order_srv/basic/config"
	__ "order_srv/basic/orderproto"
	"order_srv/handler/models"
	"order_srv/workflow"
	"time"
)

// GenerateDailyBilling 生成日账单
func GenerateDailyBilling(userID uint32, userType uint8, date string) (*models.Billing, error) {
	// 生成账单编号
	billSn := fmt.Sprintf("BILL_%s_%d_%d_%s", date, userType, userID, time.Now().Format("150405"))

	// 计算账单周期
	startTime, _ := time.Parse("2006-01-02", date)
	endTime := startTime.Add(24 * time.Hour)

	// 查询该用户当天的所有订单
	var orders []models.Orders
	err := config.DB.Where("user_id = ? AND create_at >= ? AND create_at < ?", userID, startTime, endTime).Find(&orders).Error
	if err != nil {
		return nil, err
	}

	// 计算收入和支出
	var totalIncome, totalExpense float64
	var details []models.BillingDetail

	for _, order := range orders {
		if order.OrderStatus == 5 { // 已完成订单
			// 根据用户类型计算收入或支出
			if userType == 1 { // 乘客
				detail := models.BillingDetail{
					BillingID:       0, // 稍后设置
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        2, // 支出
					ItemName:        "乘车费用",
					Amount:          order.Price,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalExpense += order.Price
			} else if userType == 2 { // 司机
				// 计算司机收入（假设平台抽成20%）
				driverRevenue := order.Price * 0.8
				detail := models.BillingDetail{
					BillingID:       0, // 稍后设置
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        1, // 收入
					ItemName:        "司机收入",
					Amount:          driverRevenue,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalIncome += driverRevenue
			}
		}
	}

	// 创建账单
	billing := &models.Billing{
		BillSn:       billSn,
		UserID:       userID,
		UserType:     userType,
		BillType:     1, // 日账单
		BillPeriod:   date,
		TotalIncome:  totalIncome,
		TotalExpense: totalExpense,
		NetAmount:    totalIncome - totalExpense,
		Status:       1, // 待确认
		GeneratedAt:  time.Now(),
		Remark:       fmt.Sprintf("自动生成的日账单，包含%d笔交易", len(details)),
	}

	// 保存账单
	err = billing.Create()
	if err != nil {
		return nil, err
	}

	// 保存账单明细
	for i := range details {
		details[i].BillingID = billing.ID
	}

	if len(details) > 0 {
		err = details[0].BatchCreate(details)
		if err != nil {
			return nil, err
		}
	}

	return billing, nil
}

// GenerateWeeklyBilling 生成周账单
func GenerateWeeklyBilling(userID uint32, userType uint8, year, week int) (*models.Billing, error) {
	// 计算周的开始和结束日期
	startDate := time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
	// 找到第一个周一
	for startDate.Weekday() != time.Monday {
		startDate = startDate.AddDate(0, 0, 1)
	}
	// 计算目标周的开始日期
	startDate = startDate.AddDate(0, 0, (week-1)*7)
	endDate := startDate.AddDate(0, 0, 7)

	// 生成账单编号
	billSn := fmt.Sprintf("BILL_W%d_%d_%d_%s", week, userType, userID, time.Now().Format("20060102150405"))

	// 查询该用户当周的所有订单
	var orders []models.Orders
	err := config.DB.Where("user_id = ? AND create_at >= ? AND create_at < ?", userID, startDate, endDate).Find(&orders).Error
	if err != nil {
		return nil, err
	}

	// 计算收入和支出
	var totalIncome, totalExpense float64
	var details []models.BillingDetail

	for _, order := range orders {
		if order.OrderStatus == 5 { // 已完成订单
			if userType == 1 { // 乘客
				detail := models.BillingDetail{
					BillingID:       0,
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        2, // 支出
					ItemName:        "乘车费用",
					Amount:          order.Price,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalExpense += order.Price
			} else if userType == 2 { // 司机
				driverRevenue := order.Price * 0.8
				detail := models.BillingDetail{
					BillingID:       0,
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        1, // 收入
					ItemName:        "司机收入",
					Amount:          driverRevenue,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalIncome += driverRevenue
			}
		}
	}

	// 创建账单
	billing := &models.Billing{
		BillSn:       billSn,
		UserID:       userID,
		UserType:     userType,
		BillType:     2, // 周账单
		BillPeriod:   fmt.Sprintf("%d年第%d周", year, week),
		TotalIncome:  totalIncome,
		TotalExpense: totalExpense,
		NetAmount:    totalIncome - totalExpense,
		Status:       1, // 待确认
		GeneratedAt:  time.Now(),
		Remark:       fmt.Sprintf("自动生成的周账单，包含%d笔交易", len(details)),
	}

	// 保存账单
	err = billing.Create()
	if err != nil {
		return nil, err
	}

	// 保存账单明细
	for i := range details {
		details[i].BillingID = billing.ID
	}

	if len(details) > 0 {
		err = details[0].BatchCreate(details)
		if err != nil {
			return nil, err
		}
	}

	return billing, nil
}

// GenerateMonthlyBilling 生成月账单
func GenerateMonthlyBilling(userID uint32, userType uint8, year, month int) (*models.Billing, error) {
	// 计算月份的开始和结束日期
	startDate := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
	endDate := startDate.AddDate(0, 1, 0)

	// 生成账单编号
	billSn := fmt.Sprintf("BILL_M%d_%d_%d_%s", month, userType, userID, time.Now().Format("20060102150405"))

	// 查询该用户当月的所有订单
	var orders []models.Orders
	err := config.DB.Where("user_id = ? AND create_at >= ? AND create_at < ?", userID, startDate, endDate).Find(&orders).Error
	if err != nil {
		return nil, err
	}

	// 计算收入和支出
	var totalIncome, totalExpense float64
	var details []models.BillingDetail

	for _, order := range orders {
		if order.OrderStatus == 5 { // 已完成订单
			if userType == 1 { // 乘客
				detail := models.BillingDetail{
					BillingID:       0,
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        2, // 支出
					ItemName:        "乘车费用",
					Amount:          order.Price,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalExpense += order.Price
			} else if userType == 2 { // 司机
				driverRevenue := order.Price * 0.8
				detail := models.BillingDetail{
					BillingID:       0,
					OrderID:         order.Id,
					OrderSn:         order.OrderSn,
					ItemType:        1, // 收入
					ItemName:        "司机收入",
					Amount:          driverRevenue,
					Description:     fmt.Sprintf("从%s到%s", order.StartLoc, order.EndLoc),
					TransactionTime: order.PayTime,
				}
				details = append(details, detail)
				totalIncome += driverRevenue
			}
		}
	}

	// 创建账单
	billing := &models.Billing{
		BillSn:       billSn,
		UserID:       userID,
		UserType:     userType,
		BillType:     3, // 月账单
		BillPeriod:   fmt.Sprintf("%d年%d月", year, month),
		TotalIncome:  totalIncome,
		TotalExpense: totalExpense,
		NetAmount:    totalIncome - totalExpense,
		Status:       1, // 待确认
		GeneratedAt:  time.Now(),
		Remark:       fmt.Sprintf("自动生成的月账单，包含%d笔交易", len(details)),
	}

	// 保存账单
	err = billing.Create()
	if err != nil {
		return nil, err
	}

	// 保存账单明细
	for i := range details {
		details[i].BillingID = billing.ID
	}

	if len(details) > 0 {
		err = details[0].BatchCreate(details)
		if err != nil {
			return nil, err
		}
	}

	return billing, nil
}

// GetBillingByUser 获取用户账单列表
func GetBillingByUser(userID uint32, userType uint8, page, pageSize int) ([]models.Billing, int64, error) {
	var billings []models.Billing
	var total int64

	query := config.DB.Model(&models.Billing{}).Where("user_id = ? AND user_type = ?", userID, userType)

	// 获取总数
	err := query.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	err = query.Offset((page - 1) * pageSize).Limit(pageSize).Order("create_at DESC").Find(&billings).Error
	if err != nil {
		return nil, 0, err
	}

	return billings, total, nil
}

// GetBillingDetails 获取账单明细
func GetBillingDetails(billingID uint32) ([]models.BillingDetail, error) {
	var details []models.BillingDetail
	err := config.DB.Where("billing_id = ?", billingID).Find(&details).Error
	return details, err
}

// ConfirmBilling 确认账单
func ConfirmBilling(billingID uint32) error {
	return config.DB.Model(&models.Billing{}).Where("id = ?", billingID).Updates(map[string]interface{}{
		"status":       2, // 已确认
		"confirmed_at": time.Now(),
	}).Error
}

// DetectAbnormalTransactions 检测异常交易
func DetectAbnormalTransactions() error {
	// 检测重复扣款
	err := detectDuplicateCharges()
	if err != nil {
		return err
	}

	// 检测金额不符
	err = detectAmountMismatch()
	if err != nil {
		return err
	}

	// 检测时间异常
	err = detectTimeAbnormal()
	if err != nil {
		return err
	}

	return nil
}

// detectDuplicateCharges 检测重复扣款
func detectDuplicateCharges() error {
	// 查询可能存在重复扣款的订单
	var duplicateOrders []struct {
		OrderSn string
		Count   int
		Amount  float64
	}

	err := config.DB.Raw(`
		SELECT order_sn, COUNT(*) as count, SUM(amount) as amount 
		FROM financial_reconciliation 
		WHERE transaction_type = 2 
		GROUP BY order_sn 
		HAVING COUNT(*) > 1
	`).Scan(&duplicateOrders).Error

	if err != nil {
		return err
	}

	// 为每个重复扣款创建异常记录
	for _, dup := range duplicateOrders {
		abnormal := &models.AbnormalTransaction{
			OrderSn:        dup.OrderSn,
			AbnormalType:   1, // 重复扣款
			AbnormalDesc:   fmt.Sprintf("订单%s被重复扣款%d次，总金额%.2f", dup.OrderSn, dup.Count, dup.Amount),
			ExpectedAmount: dup.Amount / float64(dup.Count),
			ActualAmount:   dup.Amount,
			Status:         1, // 待处理
		}

		err = abnormal.Create()
		if err != nil {
			return err
		}
	}

	return nil
}

// detectAmountMismatch 检测金额不符
func detectAmountMismatch() error {
	// 查询订单金额与财务记录不符的情况
	var mismatches []struct {
		OrderID       uint32
		OrderSn       string
		OrderAmount   float64
		FinanceAmount float64
		UserID        uint32
	}

	err := config.DB.Raw(`
		SELECT o.id as order_id, o.order_sn, o.price as order_amount, 
		       SUM(fr.amount) as finance_amount, o.user_id
		FROM orders o
		LEFT JOIN financial_reconciliation fr ON o.id = fr.order_id
		WHERE o.order_status = 5 AND fr.transaction_type = 2
		GROUP BY o.id, o.order_sn, o.price, o.user_id
		HAVING ABS(o.price - SUM(fr.amount)) > 0.01
	`).Scan(&mismatches).Error

	if err != nil {
		return err
	}

	// 为每个金额不符创建异常记录
	for _, mismatch := range mismatches {
		abnormal := &models.AbnormalTransaction{
			OrderID:        mismatch.OrderID,
			OrderSn:        mismatch.OrderSn,
			UserID:         mismatch.UserID,
			AbnormalType:   2, // 金额不符
			AbnormalDesc:   fmt.Sprintf("订单%s金额不符，订单金额%.2f，财务记录%.2f", mismatch.OrderSn, mismatch.OrderAmount, mismatch.FinanceAmount),
			ExpectedAmount: mismatch.OrderAmount,
			ActualAmount:   mismatch.FinanceAmount,
			Status:         1, // 待处理
		}

		err = abnormal.Create()
		if err != nil {
			return err
		}
	}

	return nil
}

// detectTimeAbnormal 检测时间异常
func detectTimeAbnormal() error {
	// 查询支付时间与服务时间不符的订单
	var timeAbnormals []struct {
		OrderID        uint32
		OrderSn        string
		UserID         uint32
		PayTime        time.Time
		ServiceEndTime time.Time
	}

	err := config.DB.Raw(`
		SELECT id as order_id, order_sn, user_id, pay_time, service_end_time
		FROM orders 
		WHERE order_status = 5 
		AND pay_time < service_end_time
		AND pay_time IS NOT NULL 
		AND service_end_time IS NOT NULL
	`).Scan(&timeAbnormals).Error

	if err != nil {
		return err
	}

	// 为每个时间异常创建异常记录
	for _, abnormal := range timeAbnormals {
		abnormalRecord := &models.AbnormalTransaction{
			OrderID:        abnormal.OrderID,
			OrderSn:        abnormal.OrderSn,
			UserID:         abnormal.UserID,
			AbnormalType:   3, // 时间异常
			AbnormalDesc:   fmt.Sprintf("订单%s支付时间早于服务结束时间，支付时间%s，服务结束时间%s", abnormal.OrderSn, abnormal.PayTime.Format("2006-01-02 15:04:05"), abnormal.ServiceEndTime.Format("2006-01-02 15:04:05")),
			ExpectedAmount: 0,
			ActualAmount:   0,
			Status:         1, // 待处理
		}

		err = abnormalRecord.Create()
		if err != nil {
			return err
		}
	}

	return nil
}

// ProcessAbnormalTransaction 处理异常交易
func ProcessAbnormalTransaction(abnormalID uint32, processResult string, processedBy uint32) error {
	return config.DB.Model(&models.AbnormalTransaction{}).Where("id = ?", abnormalID).Updates(map[string]interface{}{
		"status":         2, // 已处理
		"process_result": processResult,
		"processed_at":   time.Now(),
		"processed_by":   processedBy,
	}).Error
}

// CreateDispute 创建争议记录
func CreateDispute(billingID, userID uint32, disputeType uint8, disputeDesc, evidence string) (*models.DisputeRecord, error) {
	dispute := &models.DisputeRecord{
		BillingID:   billingID,
		UserID:      userID,
		DisputeType: disputeType,
		DisputeDesc: disputeDesc,
		Evidence:    evidence,
		Status:      1, // 待处理
	}

	err := dispute.Create()
	if err != nil {
		return nil, err
	}

	// 更新账单状态为有争议
	err = config.DB.Model(&models.Billing{}).Where("id = ?", billingID).Update("status", 3).Error
	if err != nil {
		return nil, err
	}

	return dispute, nil
}

// ResolveDispute 解决争议
func ResolveDispute(disputeID uint32, resolution string, resolvedBy uint32) error {
	// 更新争议记录
	err := config.DB.Model(&models.DisputeRecord{}).Where("id = ?", disputeID).Updates(map[string]interface{}{
		"status":      3, // 已解决
		"resolution":  resolution,
		"resolved_at": time.Now(),
		"resolved_by": resolvedBy,
	}).Error

	if err != nil {
		return err
	}

	// 获取争议记录以更新账单状态
	var dispute models.DisputeRecord
	err = config.DB.Where("id = ?", disputeID).First(&dispute).Error
	if err != nil {
		return err
	}

	// 更新账单状态为已确认
	err = config.DB.Model(&models.Billing{}).Where("id = ?", dispute.BillingID).Update("status", 2).Error
	if err != nil {
		return err
	}

	return nil
}

// GetAbnormalTransactions 获取异常交易列表
func GetAbnormalTransactions(status uint8, page, pageSize int) ([]models.AbnormalTransaction, int64, error) {
	var transactions []models.AbnormalTransaction
	var total int64

	query := config.DB.Model(&models.AbnormalTransaction{})
	if status > 0 {
		query = query.Where("status = ?", status)
	}

	// 获取总数
	err := query.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	err = query.Offset((page - 1) * pageSize).Limit(pageSize).Order("create_at DESC").Find(&transactions).Error
	if err != nil {
		return nil, 0, err
	}

	return transactions, total, nil
}

// GetDisputeRecords 获取争议记录列表
func GetDisputeRecords(status uint8, page, pageSize int) ([]models.DisputeRecord, int64, error) {
	var disputes []models.DisputeRecord
	var total int64

	query := config.DB.Model(&models.DisputeRecord{})
	if status > 0 {
		query = query.Where("status = ?", status)
	}

	// 获取总数
	err := query.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	err = query.Offset((page - 1) * pageSize).Limit(pageSize).Order("create_at DESC").Find(&disputes).Error
	if err != nil {
		return nil, 0, err
	}

	return disputes, total, nil
}

// parseWeekPeriod 解析周周期字符串
func ParseWeekPeriod(period string) (int, int) {
	// 假设格式为 "2024年第1周"
	// 这里简化处理，实际应该更复杂的解析
	return 2024, 1
}

// parseMonthPeriod 解析月周期字符串
func ParseMonthPeriod(period string) (int, int) {
	// 假设格式为 "2024年1月"
	// 这里简化处理，实际应该更复杂的解析
	return 2024, 1
}

// autoFixDuplicateCharge 自动修复重复扣款
func AutoFixDuplicateCharge(transaction models.AbnormalTransaction) (bool, string) {
	// 检查是否真的重复扣款
	// 这里简化处理，实际应该查询财务记录表
	if transaction.ActualAmount > transaction.ExpectedAmount {
		// 计算需要退款的金额
		refundAmount := transaction.ActualAmount - transaction.ExpectedAmount
		return true, fmt.Sprintf("检测到重复扣款，自动退款金额：%.2f元", refundAmount)
	}
	return false, "重复扣款情况复杂，需要人工核实"
}

// autoFixAmountMismatch 自动修复金额不符
func AutoFixAmountMismatch(transaction models.AbnormalTransaction) (bool, string) {
	// 检查金额差异是否在合理范围内
	diff := transaction.ActualAmount - transaction.ExpectedAmount
	if Abs(diff) <= 0.01 { // 差异小于1分钱，可能是精度问题
		return true, "金额差异在合理范围内，自动修正"
	}
	return false, "金额差异较大，需要人工核实"
}

// autoFixTimeAbnormal 自动修复时间异常
func AutoFixTimeAbnormal(transaction models.AbnormalTransaction) (bool, string) {
	// 时间异常通常需要人工处理
	return false, "时间异常需要人工核实订单状态"
}

// autoFixStatusAbnormal 自动修复状态异常
func AutoFixStatusAbnormal(transaction models.AbnormalTransaction) (bool, string) {
	// 状态异常通常需要人工处理
	return false, "状态异常需要人工核实订单状态"
}

// getAbnormalDescription 获取异常类型描述
func GetAbnormalDescription(abnormalType uint8) string {
	descriptions := map[uint8]string{
		1: "同一订单被重复扣款",
		2: "订单金额与财务记录不符",
		3: "支付时间与服务时间不符",
		4: "订单状态异常",
	}
	return descriptions[abnormalType]
}

// countResolved 统计已解决数量
func CountResolved(abnormalTransactions []models.AbnormalTransaction, disputes []models.DisputeRecord) int {
	count := 0
	for _, transaction := range abnormalTransactions {
		if transaction.Status == 2 { // 已处理
			count++
		}
	}
	for _, dispute := range disputes {
		if dispute.Status == 3 { // 已解决
			count++
		}
	}
	return count
}

// countPending 统计待处理数量
func CountPending(abnormalTransactions []models.AbnormalTransaction, disputes []models.DisputeRecord) int {
	count := 0
	for _, transaction := range abnormalTransactions {
		if transaction.Status == 1 { // 待处理
			count++
		}
	}
	for _, dispute := range disputes {
		if dispute.Status == 1 || dispute.Status == 2 { // 待处理或处理中
			count++
		}
	}
	return count
}

// abs 计算绝对值
func Abs(x float64) float64 {
	if x < 0 {
		return -x
	}
	return x
}

// processRefund 处理退款
func ProcessRefund(req *__.ManualProcessReq) (string, error) {
	// 这里应该调用支付系统的退款接口
	// 简化处理，只记录处理结果
	return fmt.Sprintf("执行退款操作：%s", req.ProcessResult), nil
}

// processAdjustment 处理调整
func ProcessAdjustment(req *__.ManualProcessReq) (string, error) {
	// 这里应该调整财务记录
	// 简化处理，只记录处理结果
	return fmt.Sprintf("执行金额调整：%s", req.ProcessResult), nil
}

// processIgnore 处理忽略
func ProcessIgnore(req *__.ManualProcessReq) (string, error) {
	// 标记为已忽略
	return fmt.Sprintf("忽略异常：%s", req.ProcessResult), nil
}

// tryAutoFix 尝试自动修复异常
func TryAutoFix(transaction models.AbnormalTransaction) (bool, string) {
	switch transaction.AbnormalType {
	case 1: // 重复扣款
		return AutoFixDuplicateCharge(transaction)
	case 2: // 金额不符
		return AutoFixAmountMismatch(transaction)
	case 3: // 时间异常
		return AutoFixTimeAbnormal(transaction)
	case 4: // 状态异常
		return AutoFixStatusAbnormal(transaction)
	default:
		return false, "未知异常类型，需要人工处理"
	}
}

// logDisputeResolution 记录争议解决日志
func LogDisputeResolution(disputeID, resolvedBy uint32, resolution string) {
	// 这里可以添加日志记录逻辑
	// 例如：记录到日志文件或数据库
	fmt.Printf("争议解决日志 - 争议ID: %d, 解决人: %d, 解决方案: %s, 时间: %s\n",
		disputeID, resolvedBy, resolution, time.Now().Format("2006-01-02 15:04:05"))
}

// sendDisputeNotification 发送争议通知
func SendDisputeNotification(disputeID uint32, message string, userID uint32) {
	// 这里可以添加通知逻辑
	// 例如：发送短信、邮件或推送通知
	fmt.Printf("争议通知 - 争议ID: %d, 消息: %s, 用户ID: %d\n", disputeID, message, userID)
}

// 全局工作流管理器
var WorkflowManager = workflow.NewWorkflowManager()

// ProcessWorkflowStep 处理工作流步骤
func ProcessWorkflowStep(ctx context.Context, workflowID, stepID, result, processedBy string) error {
	return WorkflowManager.ProcessStep(workflowID, stepID, result, processedBy)
}

// GetWorkflowStatus 获取工作流状态
func GetWorkflowStatus(ctx context.Context, workflowID string) (*workflow.DisputeWorkflow, error) {
	return WorkflowManager.GetWorkflowStatus(workflowID)
}

// EscalateDisputeWorkflow 升级争议工作流
func EscalateDisputeWorkflow(ctx context.Context, workflowID, reason string) error {
	return WorkflowManager.EscalateWorkflow(workflowID, reason)
}
